package com.geng.invoker;



import com.geng.dto.MyResponse;
import com.geng.dto.ResponseWrapper;

import java.sql.Time;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author geng
 */
public class InvokerResponseHolder {

    /**
     * 服务返回结果Map
     */
    private static final Map<String, ResponseWrapper> responseMap = new ConcurrentHashMap<>();
    /**
     * 清除过期的返回结果
     */
  //  private static final ExecutorService removeExpireKeyExecutor = Executors.newSingleThreadExecutor();

    private static final ScheduledThreadPoolExecutor removeExpireKeyExecutor = new ScheduledThreadPoolExecutor(1);

    /**
     * 定时清理间隔
     */
    private static final int RATE = 30;

    /**
     * 初始延迟
     */
    private static final int DELAY = 10;

    static {
        //删除超时未获取到结果的key,防止内存泄露
        removeExpireKeyExecutor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    for (Map.Entry<String, ResponseWrapper> entry : responseMap.entrySet()) {
                        boolean isExpire = entry.getValue().isExpire();
                        if (isExpire) {
                            responseMap.remove(entry.getKey());
                        }
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                }
                //System.out.println("InvokerResponseHolder  移除key");
            }
        }, DELAY, RATE,TimeUnit.SECONDS);
    }

    /**
     * 初始化返回结果容器,requestUniqueKey唯一标识本次调用
     *
     * @param requestUniqueKey
     */
    public static void initResponseData(String requestUniqueKey) {
        responseMap.put(requestUniqueKey, ResponseWrapper.of());
    }


    /**
     * 将Netty调用异步返回结果放入阻塞队列
     *
     * @param response
     */
    public static void putResultValue(MyResponse response) {
        long currentTime = System.currentTimeMillis();

        ResponseWrapper responseWrapper = responseMap.get(response.getUniqueKey());
        //如果已经被移除，说明过期了
        if(responseWrapper == null) return;
        responseWrapper.setResponseTime(currentTime);
        responseWrapper.getResponseQueue().add(response);
        responseMap.put(response.getUniqueKey(), responseWrapper);
    }


    /**
     * 从阻塞队列中获取Netty异步返回的结果值
     *
     * @param requestUniqueKey
     * @param timeout
     * @return
     */
    public static MyResponse getValue(String requestUniqueKey, long timeout) {
        ResponseWrapper responseWrapper = responseMap.get(requestUniqueKey);
        try {
            return responseWrapper.getResponseQueue().poll(timeout, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            responseMap.remove(requestUniqueKey);
        }
    }
}
